home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekikoh Dennoh Club 5
/
Gekikoh Dennoh Club Vol. 5 (Japan).7z
/
Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin
/
internet
/
tcppack
/
tcppackb.lzh
/
src
/
samples
/
ping.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-09
|
11KB
|
533 lines
/*
* ping.c - ping
*
* Copyright (C) 1994 Tomoaki Tada/F.C.T.
*/
static char *rcsid = "$Id: ping.c,v 1.7 1994/08/09 04:10:49 Niggle Exp $";
/*
* $Log: ping.c,v $
* Revision 1.7 1994/08/09 04:10:49 Niggle
* enable option -n
* check damaged packet
*
* Revision 1.6 1994/08/04 05:02:08 Niggle
* inetdé¬ÅφÆôé╡é─éóé╚éóÅΩìçé╠ò\Īé≡ò╧ìX
*
* Revision 1.5 1994/08/03 01:57:27 Niggle
* from addressé≡É│é╡é¡ò\Īé╖éΘéµéñé╔ò╧ìX
*
* Revision 1.4 1994/07/28 07:49:19 Niggle
* no response é╠Ä₧é╠ò\Īé≡ò╧ìX
*
* Revision 1.3 1994/07/19 05:16:38 Niggle
* duplicatesé╔æ╬ë₧
*
* Revision 1.2 1994/07/19 03:28:21 Niggle
* cksumé╠ìéæ¼ë╗
* usageé╠ò\Ī
* é╗é╠æ╝éóéδéóéδ
*
* Revision 1.1 1994/06/23 03:56:12 Niggle
* Initial revision
*
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<signal.h>
#include<limits.h>
#ifdef __human68k__
#undef __DOS_INLINE__
#define __DOS_INLINE__
#include<sys/dos.h>
#endif
#include"network.h"
#include"socket.h"
#include"ping.h"
static int send_request (int, long, unsigned short, unsigned short, unsigned short);
static int doping (long, long, long, long);
static void ping_recv (void);
static void ping_send (void);
static void handler (int);
static unsigned short eac (long);
static unsigned short cksum (unsigned char *, unsigned short);
static void display_ratio (void);
static volatile void display_usage (void);
static int isnumstr (const unsigned char *);
static void check_data (const unsigned char *, int);
static int ping_socket = -1;
static struct ping ping;
static int no_convert_p;
static int sending;
static char *hostname, *ipaddr;
struct mib_entry *icmp_mib;
/************************************************
* *
************************************************/
void
main (int argc, char **argv)
{
int i, c;
long target, interval, count, size;
struct mib_array *top;
top = get_mib_list ();
if (!top)
{
fprintf (stderr, "TCP/IP driveré═ÅφÆôé╡é─éóé▄é╣é±\n");
return;
}
for (i = 0; i < 4; i++)
{
if (!strcmp (top[i].name, "ICMP"))
break;
}
if (i < 4)
icmp_mib = top[i].mib;
else
icmp_mib = NULL;
count = -1;
interval = 1;
opterr = 1;
size = 56;
while ((c = getopt (argc, argv, "c:i:n")) != EOF)
{
switch (c)
{
case 'c':
if (!isnumstr (optarg))
display_usage ();
count = atol (optarg);
if (count < 1)
count = 1;
break;
case 'i':
if (!isnumstr (optarg))
display_usage ();
interval = atol (optarg);
if (interval < 1)
interval = 1;
break;
case 'n':
no_convert_p = 1;
break;
case '?':
break;
default:
break;
}
}
if (optind < argc)
{
char _ipaddr[64];
if (isipaddr (argv[optind]))
{
target = a2n_ipaddr (argv[optind]);
ipaddr = argv[optind];
}
else
{
struct hostent *h;
h = gethostbyname (argv[optind]);
if (h)
{
target = *(long *)h->h_addr;
ipaddr = n2a_ipaddr (target, _ipaddr);
}
else
{
ipaddr = NULL;
target = 0;
}
}
hostname = argv[optind];
if (target)
{
signal (SIGINT, handler);
doping (target, size, interval, count);
signal (SIGINT, SIG_DFL);
}
else
fprintf (stderr, "ping: host name look up failed\n");
}
else
display_usage ();
return;
}
/************************************************
* *
************************************************/
static void
display_ratio (void)
{
double sent, res, avg;
sent = ping.sent;
if (sending)
{
sent -= 1;
ping.sent -= 1;
}
res = ping.responses;
avg = res / sent * 100;
avg = 100.0 - avg;
printf ("\n");
/* display rate */
printf ("--- %s ping statistics ---\n", hostname);
if (ping.dup)
{
printf ("%d packets transmitted, %d packets received, +%d duplicates, %.2f%% packet loss\n",
ping.sent, ping.responses, ping.dup, avg);
}
else
{
printf ("%d packets transmitted, %d packets received, %.2f%% packet loss\n",
ping.sent, ping.responses, avg);
}
if (ping.responses)
printf ("round-trip min/avg/max = %d/%.2f/%d ms\n",
ping.mrtt, (double)ping.srtt / res, ping.Mrtt);
else
printf ("round-trip min/avg/max = 0/0/0 ms\n");
fflush (stdout);
return;
}
/************************************************
* *
************************************************/
static void
handler (int dummy)
{
if (ping_socket)
close_s (ping_socket);
display_ratio ();
exit (0);
}
/************************************************
* *
************************************************/
static int
doping (long target, long len, long interval, long count)
{
int i;
memset ((char *) &ping, 0, sizeof (ping));
ping_socket = socket (AF_INET, SOCK_RAW, ICMP_PCTL);
if (ping_socket == -1)
return 1;
ping.target = target;
ping.mrtt = LONG_MAX;
ping.Mrtt = LONG_MIN;
ping.len = len;
ping.interval = interval *= CLOCKS_PER_SEC;
printf ("PING %s (%s): %d data bytes\n", hostname, ipaddr, len);
fflush (stdout);
ping.sent = 0;
if (count >= 0)
{
for (i = 0; i < count; i++)
{
clock_t start;
start = clock ();
sending = 1;
ping_send ();
while (clock () - start < interval)
{
ping_recv ();
#ifdef __human68k__
/* check ^C */
if (_dos_keysns ())
_dos_getchar ();
#endif
}
ping.lost = ping.sent - ping.responses;
}
}
else
{
for (;;)
{
clock_t start;
start = clock ();
sending = 1;
ping_send ();
while (clock () - start < interval)
{
ping_recv ();
#ifdef __human68k__
/* check ^C */
if (_dos_keysns ())
_dos_getchar ();
#endif
}
sending = 0;
ping.lost = ping.sent - ping.responses;
}
}
close_s (ping_socket); ping_socket = -1;
display_ratio ();
return 0;
}
/************************************************
* *
************************************************/
static void
ping_send (void)
{
send_request (ping_socket, ping.target, ping.sent++, ping_socket, ping.len);
}
/************************************************
* *
************************************************/
static void
ping_recv (void)
{
struct icmp icmp;
long timestamp, rtt;
struct sockaddr_in from;
int fromlen;
int len;
int dup_p;
char buff[2048];
char _hostname[64];
clock_t now;
now = clock ();
fromlen = sizeof (from);
if (!socklen (ping_socket, 0))
return;
len = recvfrom (ping_socket, buff, ping.len + sizeof (struct icmp),
0, (char *) &from, &fromlen);
if (len == -1)
return;
sending = 0;
memcpy (&icmp, buff, sizeof (struct icmp));
if (icmp.type != ICMP_ECHO_REPLY || icmp.id != ping_socket)
return;
dup_p = 0;
if (ping.sent == ping.responses + 1 + ping.lost)
ping.responses++;
else
{
dup_p = 1;
ping.dup++;
}
/* Get stamp */
memcpy ((char *)×tamp, buff + sizeof (struct icmp), sizeof (timestamp));
{
struct hostent *h;
long from_ip;
from_ip = from.sin_addr.s_addr;
if (!no_convert_p)
{
h = gethostbyaddr ((char *)&from_ip, sizeof (long), AF_INET);
if (h)
{
char *dot;
strcpy (_hostname, h->h_name);
dot = strchr (_hostname, '.');
if (dot)
{
if (!strcmp (dot + 1, get_domain_name ()))
*dot = '\0';
}
}
else
n2a_ipaddr (from_ip, _hostname);
}
else
n2a_ipaddr (from_ip, _hostname);
}
/* Compute round trip time, update smoothed estimates */
rtt = (now - timestamp) * (1000 / CLOCKS_PER_SEC);
printf ("%d bytes from %s: icmp_seq=%d time=%d ms",
len, _hostname, icmp.seq, rtt);
if (dup_p)
printf (" (DUP!)\n");
else
printf ("\n");
check_data (buff, len - sizeof (struct icmp));
if (ping.mrtt > rtt)
ping.mrtt = rtt;
if (ping.Mrtt < rtt)
ping.Mrtt = rtt;
ping.srtt += rtt;
fflush (stdout);
}
/************************************************
* *
************************************************/
static int
send_request (int s, long target, unsigned short seq, unsigned short id, unsigned short len)
{
struct icmp *icmp;
struct sockaddr_in to;
char data[2048];
/* Set optional data field, if any, to all 55's */
if (len != 0)
{
char *p;
int i;
p = data + sizeof (struct icmp);
for (i = 0; i < len; i++)
*p++ = (char)i;
}
/* Insert timestamp and build ICMP header */
*(clock_t *)(data + sizeof (struct icmp)) = clock ();
if (icmp_mib)
{
icmp_mib[21].value.integer++;
icmp_mib[14].value.integer++;
}
icmp = (struct icmp *)&data;
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->cksum = 0;
icmp->seq = seq;
icmp->id = id;
icmp->cksum = cksum ((unsigned char *)icmp, sizeof (struct icmp) + ping.len);
to.sin_family = AF_INET;
to.sin_addr.s_addr = target;
sendto (ping_socket, data, sizeof (struct icmp) + len, 0, (char *) &to, sizeof (to));
return 0;
}
/************************************************
* 16bit é┼ 1é╠òΓÉöé╠ÿaé╠îπÄnûû *
************************************************/
static unsigned short
eac (long sum)
{
unsigned short csum;
while ((csum = sum >> 16) != 0)
sum = csum + (sum & 0xffff);
return (unsigned short) (sum & 0xffff);
}
/************************************************
* *
************************************************/
static unsigned short
cksum (unsigned char *_m, unsigned short _len)
{
long sum;
int len;
unsigned short *p;
len = _len >> 1;
p = (unsigned short *)_m;
sum = 0;
while (len-- != 0)
sum += *p++;
return ~eac (sum) & 0xffff;
}
/************************************************
* *
************************************************/
static int
isnumstr (const unsigned char *target)
{
return strspn ((char *)target, "0123456789") == strlen (target);
}
/************************************************
* *
************************************************/
static volatile void
display_usage (void)
{
printf ("usage: ping [-c count] [-i interval] host\n");
exit (0);
}
/************************************************
* *
************************************************/
static void
check_data (const unsigned char *buff, int size)
{
const unsigned char *p;
int i, bad;
bad = 0;
p = buff + sizeof (struct icmp) + sizeof (clock_t);
for (i = sizeof (clock_t); i < size; i++, p++)
{
int c;
c = *p;
if (c != i)
{
printf ("wrong data byte #%d should be 0x%x was 0x%x\n", i, i, c);
bad++;
}
}
if (bad)
{
for (i = 0, p = buff + sizeof (struct icmp); i < size; i++, p++)
{
if (!i)
printf ("\t");
else if (!(i % 24))
printf ("\n\t");
printf ("%2.2x ", *p);
}
printf ("\n");
}
}